package com.xspace.android.xafcommon.download;

import android.util.Log;

import com.xspace.android.xafcommon.network.NetConstant;
import com.xspace.android.xafcommon.network.apn.ApnUtil;
import com.xspace.android.xafcommon.network.apn.ApnUtil.APNname;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Observable;

public class DownloadThread extends Observable implements Runnable {

    private long downloaded; // already download size

    private int mNumber; // present downloaded task

    private long mCurrentDownloaded; // present task downloaded size

    private long size;

    public int status; // present download status

    private DownloadInfo mDownload = null; // need dowanload task

    private String id; // task id

    private float speed;// speed

    private long startTime = 0;

    private int endTime = 1;

    public boolean downType;

    //    private IDownCallback mDownCallback;
    private IDownloadListener mDownListener;
    private DownloadManager mDownloadManager;

    public DownloadThread(String id, DownloadInfo downloads,
                          DownloadManager manager) {
        downloaded = 0;
        mDownloadManager = manager;
        status = DownConstants.START;
        this.id = id;
        mDownload = downloads;
        mNumber = 0;
        mCurrentDownloaded = 0;
        stateChanged();
    }

    public String getId() {
        return id;
    }

    public int getCurrentNumber() {
        return mNumber;
    }

    public long getDownloaded() {
        return downloaded;
    }

    public DownloadInfo getDownloads() {
        return mDownload;
    }

    public long getSize() {
        return size;
    }

    public float getProgress() {
        return ((float) downloaded / size) * 100;
    }

    public float getSpeed() {

        int time = (int) (getTime() - startTime) / 1000;
        if (time != 0) {
            speed = downloaded / time;
        }
        return speed;
    }

    public int getStatus() {
        return status;
    }

    public void pause() {
        status = DownConstants.PAUSED;
        stateChanged();
    }

    public void resume() {
        status = DownConstants.DOWNLOADING;
        stateChanged();
        download();
    }

    public void cancel() {
        status = DownConstants.CANCELLED;
        stateChanged();
    }

    private void error() {
        status = DownConstants.ERROR;
        stateChanged();
    }

    private void download() {
        Thread thread = new Thread(this);
        thread.start();
    }

    private long getTime() {
        return new Date().getTime();
    }

    public void run() {
        if (!downType) {
            setmDownCallback(mDownloadManager.getCallback(id));
        }
        LoadInfo info = mDownload.req;
        FileOutputStream file = null;
        InputStream stream = null;
        BufferedOutputStream bos = null;
        File fileLoad = null;
        size = mDownload.size;
        try {
            FileUtils.initDir(info.exsitDir, info.directory);
            FileUtils.newFile(mDownload.tmpFileName);
            fileLoad = new File(mDownload.tmpFileName);
            if (!fileLoad.exists()) {
                try {
                    fileLoad.createNewFile();
                } catch (IOException e) {
                }
            } else {
                FileInputStream fileInput = new FileInputStream(fileLoad);
                mCurrentDownloaded = fileInput.available();
                downloaded = mCurrentDownloaded;
                fileInput.close();
            }
            file = new FileOutputStream(mDownload.tmpFileName, true);
            bos = new BufferedOutputStream(file, 1024 * 1024);
            HttpEntity entity = null;
            entity = getConnection(info.downloadUrl);
            if (status < DownConstants.ERROR) {
                stream = entity.getContent();
                if (stream == null) {
                    error();
                    return;
                }
                long leng = entity.getContentLength();
                if (leng > 0) {
                    size = leng;
                }
                startTime = getTime();
                byte buffer[] = new byte[DownConstants.MAX_BUFFER_SIZE];
                while (status == DownConstants.DOWNLOADING) {
                    int read = stream.read(buffer);
                    if (read == -1)
                        break;
                    bos.write(buffer, 0, read);
                    mCurrentDownloaded += read;
                    downloaded = mCurrentDownloaded;
                    stateChanged();
                }
            }
            if (status == DownConstants.PAUSED
                    || status == DownConstants.CANCELLED
                    || status == DownConstants.ERROR) {
                stateChanged();
            }
            mCurrentDownloaded = 0;
            bos.flush();
            mNumber++;

        } catch (Exception e) {
            e.printStackTrace();
            error();
        } finally {
            if (file != null) {
                try {
                    bos.flush();
                    file.close();
                    bos.close();
                    fileLoad.canWrite();
                } catch (Exception e) {
                }
            }
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (status == DownConstants.DOWNLOADING) {
                status = DownConstants.COMPLETE;
                stateChanged();
            }
        }
    }

    private HttpEntity getConnection(String url) {
        HttpEntity entity = null;
        try {
            HttpClient client = new DefaultHttpClient();
            boolean isCMWap = ApnUtil.isWap();
            if (isCMWap) {
                String proxyIp = "10.0.0.172";
                String wrapname = ApnUtil.getWapName();
                //电信多种机型测试发现接入点名称大都为#777或者null 使用排除法确定
                if (APNname.WAP_3G.equals(wrapname) || APNname.CMWAP.equals(wrapname) || APNname.UNIWAP.equals(wrapname)) {

                } else {
                    proxyIp = "10.0.0.200";
                    Log.v("xafcommon", "getConnection  " + proxyIp + " wrapname:" + wrapname);
                }
                HttpHost proxy = new HttpHost(proxyIp, 80);
                client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
                        proxy);
            }
            HttpGet get = new HttpGet(url);
            HttpResponse response;
            if (NetConstant.cookieStore != null) {
                ((AbstractHttpClient) client)
                        .setCookieStore(NetConstant.cookieStore);
            }
            client.getParams().setParameter(
                    CoreConnectionPNames.CONNECTION_TIMEOUT, 1000 * 30);
            client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
                    1000 * 30);
            if (!downType && DownConstants.reseedFlag) {//Breakpoint continuingly
                get.addHeader("RANGE",
                        "bytes=" + String.valueOf(mCurrentDownloaded) + "-");
            }
            response = client.execute(get);
            NetConstant.cookieStore = ((AbstractHttpClient) client)
                    .getCookieStore();
            int code = response.getStatusLine().getStatusCode();
            if (code / 200 != 1) {
                error();
            }
            entity = response.getEntity();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return entity;
    }

    @SuppressWarnings("unused")
    private boolean isWap() {
        String proxyHost = android.net.Proxy.getDefaultHost();
        if (proxyHost != null) {
            return true;
        } else {
            return false;
        }
    }

    // Notify observers that this download's status has changed.
    private void stateChanged() {
        setChanged();
        notifyObservers();
    }

    public void setEndTime(int endTime) {
        this.endTime = endTime;
    }

    public int getEndTime() {
        return endTime;
    }

    public void setmDownCallback(IDownloadListener mDownCallback) {
        this.mDownListener = mDownCallback;
    }

//    public IDownCallback getmDownCallback() {
//        return mDownCallback;
//    }
}
